/*
 * Copyright 2008 M-Way Solutions
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mwaysolutions.ocm.impl;

import java.util.HashMap;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;

import com.mwaysolutions.ocm.OcmException;
import com.mwaysolutions.ocm.OcmProcessor;
import com.mwaysolutions.ocm.OcmReader;
import com.mwaysolutions.ocm.OcmRegister;
import com.mwaysolutions.ocm.OcmTypeRegister;
import com.mwaysolutions.ocm.OcmWriter;


/**
 *
 * @author <a href="mailto:m.zdila@mwaysolutions.com">Martin Ždila</a>
 */
public class OcmProcessorImpl implements OcmProcessor {

	private final OcmTypeRegister ocmTypeRegister;
	private final OcmRegister ocmRegister;


	@Override
	public OcmTypeRegister getOcmTypeRegister() {
		return ocmTypeRegister;
	}


	public OcmProcessorImpl(final OcmTypeRegister ocmTypeRegister, final OcmRegister ocmRegister) {
		this.ocmTypeRegister = ocmTypeRegister;
		this.ocmRegister = ocmRegister;
	}


	@Override
	public Object get(final Node node) throws RepositoryException, OcmException {
		final OcmReaderImpl ocmReader = new OcmReaderImpl(ocmTypeRegister, new HashMap<IsSameItemEqualsWrapper, Object>());
		return ocmReader.get(node, ocmReader);
	}


	@Override
	public Item saveOrUpdate(final Session session, final String targetNodePath, final Object object) throws RepositoryException, OcmException {
		final int c = targetNodePath.lastIndexOf('/');
		return saveOrUpdate((Node) session.getItem(targetNodePath.substring(0, c)), targetNodePath.substring(c + 1), object);
	}


	@Override
	public Item save(final Node parentNode, final String name, final Object object) throws RepositoryException, OcmException {
		final OcmWriter ocmWriter = createOcmWriter();
		final Item result = ocmWriter.saveOrUpdate(parentNode, name, object, false, true, ocmWriter);
		ocmWriter.saveDelayedReferences();
		return result;
	}


	@Override
	public Item saveOrUpdate(final Node parentNode, final String name, final Object object) throws RepositoryException, OcmException {
		final OcmWriter ocmWriter = createOcmWriter();
		final Item result = ocmWriter.saveOrUpdate(parentNode, name, object, false, false, ocmWriter);
		ocmWriter.saveDelayedReferences();
		return result;
	}


	@Override
	public void saveOrUpdate(final Node node, final Object value) throws OcmException, RepositoryException {
		final OcmWriter ocmWriter = createOcmWriter();
		ocmWriter.saveOrUpdate(node, value, ocmWriter);
		ocmWriter.saveDelayedReferences();
	}


	@Override
	public void registerType(final Workspace workspace, final Class<?> clazz, final String name) throws RepositoryException {
		ocmRegister.registerType(workspace, clazz, name, false);
	}


	@Override
	public void registerType(final Workspace workspace, final Class<?>... classes) throws RepositoryException {
		for (final Class<?> clazz : classes) {
			ocmRegister.registerType(workspace, clazz, false);
		}
	}


	@Override
	public void reregisterType(final Workspace workspace, final Class<?>... classes) throws RepositoryException {
		for (final Class<?> clazz : classes) {
			ocmRegister.registerType(workspace, clazz, true);
		}
	}


	@Override
	public void reregisterType(final Workspace workspace, final Class<?> clazz, final String name) throws RepositoryException {
		ocmRegister.registerType(workspace, clazz, true);
	}


	@Override
	public OcmReader createOcmReader() {
		return new OcmReaderImpl(ocmTypeRegister, new HashMap<IsSameItemEqualsWrapper, Object>());
	}


	@Override
	public OcmWriter createOcmWriter() {
		return new OcmWriterImpl(ocmTypeRegister, new HashMap<Object, Node>());
	}

}
